#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <time.h>
#include <getopt.h>
#include <mpi.h>
using namespace std;

#include "body.h"

#define DELTA_T 1000

int main(int argc, char *argv[])
{
	/* MPI setup */
	//MPI_Comm comm;
	//MPI_Status status;
	//MPI_Request request;
	char hostname[50];
	int nodes, rank;
	//double time[2];
	//double runtime;

	MPI_Init(&argc, &argv);
	MPI_Comm_rank (MPI_COMM_WORLD, &rank);
	MPI_Comm_size (MPI_COMM_WORLD, &nodes);
	gethostname(hostname, 50);
	
	//printf("# I'm process %2d out of %2d (%s)\n", rank, nodes, hostname);
	MPI_Barrier(MPI_COMM_WORLD);

	/* parse options */
	int c;
	int optBodys = 0;
	int optIterations = 0;
	int optPrintFlag = 0;
	
	if (argc >= 1+2+2)
	{
		while ((c = getopt(argc, argv, "b:i:p")) != -1)
		{
			switch (c)
			{
				case 'b':
					optBodys = atoi(optarg) >= 1 ? atoi(optarg) : 10;
					break;
				case 'i':
					optIterations = atoi(optarg) >= 1 ? atoi(optarg) : 1000;
					break;
				case 'p':
					optPrintFlag = 1;
					break;
				default:
					break;
			}
		}
		#if 0
		if (rank == 0) std::cout << "optBodys=" << optBodys << std::endl;
		if (rank == 0) std::cout << "optIterations=" << optIterations << std::endl;
		if (rank == 0) std::cout << "optPrintFlag=" << optPrintFlag << std::endl;
		#endif
	}
	else
	{
		printf("Syntax Error!\n");
		printf("Usage: %s -b bodys -i iterations [OPTIONS]\n", argv[0]);
		printf("Options:\n");
		printf("\t-p\t\tprint coordinates\n");
		
		MPI_Finalize();
		return -1;
	}

	Body *bodys = new Body[optBodys];
	if (rank == 0) std::cout << "nbodys=" << bodys[0].getBodyCount() << std::endl;

	/* sequential */
	if (rank == 0)
	{
		/* init bodys */
		for (int i=0; i<optBodys; i++)
		{
			bodys[i].setDt(DELTA_T);
			bodys[i].setMass(rand()%1000 + 1);
			bodys[i].setPos(rand()%10-5, rand()%10-5, rand()%10-5);
		}
		
		/* perform simulation */
		for (int i=0; i<optIterations; i++)
		{
			if (optPrintFlag == 1) printf("%2d: ", rank);
			for (int j=0; j<optBodys; j++)
			{
				if (optPrintFlag == 1)
				{
					static char output[50];
					strcpy(output, "%4.2lf %4.2lf %4.2lf    ");   // debug view
					//strcpy(output, "%12.9lf %12.9lf %12.9lf "); // plot view
					printf(output, bodys[j].posx, bodys[j].posy, bodys[j].posz);
				}
				bodys[j].calcNewPos(bodys);
			}
			if (optPrintFlag == 1) printf("\n");
		}
	}

	/* clean up */
	delete [] bodys;
	printf("# %2d: done\n", rank);
	MPI_Finalize();
	return 0;
}

